#include "Druide.h"
#include <iostream>
//#include "lib.h"
using namespace std;

const unsigned int Druide::nbr_comp = 75;

const unsigned int Druide::nbr_restric = 0;

ListComp Druide::Comp[75] = {
  {"Amitié avec les animaux"                    , 5 , false},
  {"Communication avec les créatures sylvestres", 10, false},
  {"Déplacement silencieux"                     , 5 , false},
  {"Dés de vie à 1d10"                          , 10, false},
  {"Identification"                             , 5 , false},
  {"Immunité aux charmes (niv 7)"               , 5 , false},
  {"Immunité aux charmes"                       , 10, false},
  {"Immunité aux maladies"                      , 10, false},
  {"Langue des initiés"                         , 5 , false},
  {"Maîtrise élémentiare"                       , 5 , false},
  {"Changement de forme (dès niv 5)"            , 15, false},
  {"Changement de forme (niv 7)"                , 10, false},
  {"Passage sans traces"                        , 5 , false},
  {"Purification de l'eau"                      , 5 , false},
  {"Résistance au feu et à l'électricité"       , 5 , false},
  {"Résistance au froid"                        , 5 , false},
  {"Se cacher dans l'ombre"                     , 5 , false},
  {"Spécialisation"                             , 15, false},
  {"Sélection de sphères standard"              , 60, false},
  // -> 19
  {"G\\'en\\'erale (min)"                       , 3 , false},
  {"Animale (min)"                              , 5 , false},
  {"Astrale (min)"                              , 3 , false},
  {"Chaos (min)"                                , 5 , false},
  {"Charme (min)"                               , 5 , false},
  {"Climat (min)"                               , 3 , false},
  {"Combat (min)"                               , 5 , false},
  {"Cr\\'eation (min)"                          , 5 , false},
  {"Divination (min)"                           , 5 , false},
  {"El\\'ementaire (min)"                       , 8 , false},
  {"Air (min)"                                  , 2 , false},
  {"Eau (min)"                                  , 2 , false},
  {"Feu (min)"                                  , 3 , false},
  {"Terre (min)"                                , 3 , false},
  {"Garde (min)"                                , 3 , false},
  {"Guerre (min)"                               , 3 , false},
  {"Invocation (min)"                           , 5 , false},
  {"Loi (min)"                                  , 5 , false},
  {"N\\'ecromancie (min)"                       , 5 , false},
  {"Nombres (min)"                              , 5 , false},
  {"Pens\\'ee (min)"                            , 5 , false},
  {"Protection (min)"                           , 5 , false},
  {"Soin (min)"                                 , 5 , false},
  {"Soleil (min)"                               , 3 , false},
  {"Temps (min)"                                , 5 , false},
  {"V\\'eg\\'etale (min)"                       , 5 , false},
  {"Vigilance (min)"                            , 5 , false},
  {"Voyageur (min)"                             , 3 , false},
  // -> 47
  {"G\\'en\\'erale (maj)"                       , 5 , false},
  {"Animale (maj)"                              , 10, false},
  {"Astrale (maj)"                              , 6 , false},
  {"Chaos (maj)"                                , 8 , false},
  {"Charme (maj)"                               , 10, false},
  {"Climat (maj)"                               , 10, false},
  {"Combat (maj)"                               , 10, false},
  {"Cr\\'eation (maj)"                          , 10, false},
  {"Divination (maj)"                           , 10, false},
  {"El\\'ementaire (maj)"                       , 20, false},
  {"Air (maj)"                                  , 5 , false},
  {"Eau (maj)"                                  , 5 , false},
  {"Feu (maj)"                                  , 8 , false},
  {"Terre (maj)"                                , 8 , false},
  {"Garde (maj)"                                , 5 , false},
  {"Guerre (maj)"                               , 5 , false},
  {"Invocation (maj)"                           , 10, false},
  {"Loi (maj)"                                  , 8 , false},
  {"N\\'ecromancie (maj)"                       , 10, false},
  {"Nombres (maj)"                              , 10, false},
  {"Pens\\'ee (maj)"                            , 10, false},
  {"Protection (maj)"                           , 10, false},
  {"Soin (maj)"                                 , 10, false},
  {"Soleil (maj)"                               , 5 , false},
  {"Temps (maj)"                                , 10, false},
  {"V\\'eg\\'etale (maj)"                       , 10, false},
  {"Vigilance (maj)"                            , 10, false},
  {"Voyageur (maj)"                             , 5 , false}
  // -> 75
};

Druide::Druide(unsigned int xp, unsigned int trait[7], unsigned int& PP)
  : Classe(xp, trait, Pretres)
{
  Type_classe = "Druide";
  PP += 100;
  dout(BLANK) << "********************************************************" << endl;
  dout(BLANK) << "Création d'un druide" << endl << endl;
  unsigned int nbr(0);

  dout(BLANK) << "Tu as " << PP << " pp à dépenser" << endl;

  for (unsigned int i(0); i<nbr_comp; i++)
    {
      if (Comp[i].Cout != 0)
	dout(BLANK) << i+1 << ' ' << affiche_accent(Comp[i].Comp)
		    << " (" << Comp[i].Cout << " pp)" << endl;
      else
	dout(BLANK) << i+1 << ' ' << affiche_accent(Comp[i].Comp)
		    << " (cout variable)" << endl;	
    }
  dout(BLANK) << nbr_comp+1 << " Aucune" << endl;
  dout(BLANK) << "Choisir les compétences de classe" << endl;

  bool test(true), deja_pris, encore(false);
  unsigned int save_PP(PP);
  
  do
    {
      do
	{
	  nbr = demander_unsigned_borne("("+write_int(PP)+" restants) ", 1,
					nbr_comp + 1);
      
	  if (nbr!=nbr_comp+1)
	    {
	      if (nbr != 19)
		{
		  deja_pris = safe_push_back(&Comp_classe, nbr - 1);
		  if (deja_pris)
		    dout(WARN) << "Déjà sélectionné" << endl;
		  else
		    {
		      if (PP >= Comp[nbr-1].Cout)
			{
			  Comp_classe.push_back(nbr-1);
			  PP -= Comp[nbr-1].Cout;
			  dout(BLANK) << "Compétence choisie : "
				      << affiche_accent(Comp[nbr-1].Comp) << endl;
			}
		      else
			dout(BLANK) << "Pas assez de pp" << endl;
		    }
		}
	      else
		if (PP >= 60)
		  {
		    unsigned int spheres[11] = {70, 47, 48, 52, 56, 57, 58,
						59, 60, 69, 72};
		    for (unsigned int i(0); i<11; i++)
		      Comp_classe.push_back(spheres[i]);
		    PP -= Comp[nbr-1].Cout;
		    dout(BLANK) << affiche_accent(Comp[nbr-1].Comp) << endl;
		  }
		else
		  dout(BLANK) << "Pas assez de pp" << endl;
	    }
	  else
	    test = false;
	}
      while(test);

      affiche_competences();
      dout(BLANK) << endl <<  "1 pour continuer, 2 pour recommencer" << endl;
      nbr = demander_unsigned_borne("Choix ", 1, 2);
      if (nbr == 2)
	{
	  PP = save_PP;
	  Comp_classe.clear();
	  test = true;
	  encore = true;
	  dout(BLANK) << endl;
	}
      else
	encore = false;
    }
  while(encore);

  dout(BLANK) << endl << setfill('*') << setw(56) << '*' << setfill(' ')
	      << endl;
  calcul_niveau();
  calcul_niv_mag();
}

Druide::Druide(unsigned int xp, unsigned int trait[7])
  : Classe(xp, trait, Pretres)
{
  Type_classe = "Druide";
  calcul_niveau();
}

Druide::~Druide()
{}

void Druide::calcul_niveau()
{
  if (XP < 7500)
    Niveau = XP / 2000 + 1;
  else if (XP < 12500)
    Niveau = 4;
  else if (XP < 20000)
    Niveau = 5;
  else if (XP < 35000)
    Niveau = 6;
  else if (XP < 125000)
    Niveau = (XP - 60000) / 30000 + 8;
  else if (XP < 200000)
    Niveau = 11;
  else if (XP < 300000)
    Niveau = 12;
  else if (XP < 3500000)
    {
      unsigned int i;
	for (i = 0; i < 4; i++)
	  {
	    if (XP < (unsigned int) 750000 * puissance(2, i))
	      break;
	  }
      Niveau = i + 12;
    }
}

void Druide::afficher_stats()
{
  dout(BLANK) << "Druide" << endl;
  for (unsigned int i(0); i<6; i++)
    dout(BLANK) << Caracteristiques[i] << ' ' << Traits[i] << endl;
  for (unsigned int i(0); i<Comp_classe.size(); i++)
    dout(BLANK) << affiche_accent(Comp[Comp_classe[i]].Comp) << endl;
}

void Druide::appliquer_modif(const string& type)
{}

void Druide::augmenter_talents(const unsigned int& bonus, const bool& lvl_up)
{}

void Druide::get_JS(unsigned int *tab) const
{
  *(tab + 0) = 13; // Paralysie, Poison ou Mort magique
  *(tab + 1) = 14; // Bâton, batonnet baguette
  *(tab + 2) = 12; // Pétrification ou Métamorphose
  *(tab + 3) = 16; // Souffles
  *(tab + 4) = 15; // Sorts
  
  unsigned int cat;
  if (Niveau <= 4)
    cat = 0;
  else  if (Niveau <= 8)
    cat = 1;
  else  if (Niveau <= 12)
    cat = 2;
  else  if (Niveau <= 16)
    cat = 3;
  else  if (Niveau <= 20)
    cat = 4;
  else
    cat = 5;

  *(tab + 0) -= cat;
  *(tab + 1) -= cat;
  *(tab + 2) -= cat;
  *(tab + 3) -= cat;
  *(tab + 4) -= cat;
}


string Druide::get_competence(const unsigned int& i) const
{
  if (get_comp(i) < nbr_comp)
    return affiche_accent(Comp[get_comp(i)].Comp);
  else
    return "Petit problème";
  //  return Restric[get_comp(i)-nbr_comp];
}

unsigned int Druide::calcule_TAc0() const
{
  unsigned int mod_niveau(2 * ((Niveau - 1) / 3));

  return 20 - mod_niveau;
}

void Druide::calcul_niv_mag()
{
  if (Niveau < 16)
    Niveau_mag = (Niveau + 1) / 2;
  else
    Niveau_mag = 7;
}

void Druide::ecrire_sorts(const string& nom_fichier, const bool& ecrase) const
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(fonction);
  ofstream sortie;
  string nom_complet, tmp;
  dout(FUNC) << "A écrire : " << nom_fichier << endl;

  if (ecrase)
    /*
     * Ecrase l'éventuel contenu du fichier
     */
    {
      sortie.open(nom_fichier.c_str());
      dout(DEBUG) << "Ouverture                [ OK ]" << endl;
    }
  else
    /*
     * Alors on ouvre le fichier de telle sorte à écrire à la suite
     */
    {
      sortie.open(nom_fichier.c_str(), ios::app);
      dout(DEBUG) << "Ouverture                [ OK ]" << endl;
    }

  unsigned int taille(get_combien()), loc;

  for (unsigned int i(0); i < taille; i++)
    {
      if (get_comp(i) > 2)
	{
	  tmp = get_competence(i);
	  dout(LINFO) << "Check sphère : " << tmp << endl;
	  loc = tmp.find(" (m", 0);
	  if (loc == string::npos)
	    {
	      dout(LFUNC) << "Pas une sphère..." << endl;
	      continue;
	    }
	  
	  tmp.replace(loc, 6, "");
	  for (unsigned int j(1); j <= Niveau_mag; j++)
	    {
	      if (get_comp(i) < 71 && j > 3)
		/*
		 * Accès mineur => jusqu'au lvl 3 uniquement!
		 */
		break;
	      dout(DEBUG) << "accents loin " << supprime_accents(tmp) << endl;
	      sortie << "\\input{../../Sorts_clerc/" << supprime_accents(tmp)
		     << "_"  << write_int(j) << ".inc.tex}" << endl;
	      
	    }
	  
	}
    }
  sortie.close();
  dout.setLevel(etat_precedent);
}

void Druide::nbr_sort(unsigned int sorts[], const unsigned int& taille) const
{
  DebugLevelType etat_precedent(dout.getLevel());
  dout.setLevel(fonction);
  dout(DEBUG) << "Fait rien pour le moment, recopier de Clerc.cc" << endl;
  dout.setLevel(etat_precedent);
}
